package org.springblade.auth.endpoint;

import com.alibaba.fastjson.JSON;
import com.github.xiaoymin.knife4j.annotations.ApiSort;
import io.swagger.annotations.Api;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.RandomStringUtils;
import org.shy.core.sso.client.util.SsoUtil;
import org.shy.core.sso.common.entity.SsoUser;
import org.shy.core.sso.common.entity.SsoUserInfo;
import org.springblade.auth.constant.AuthConstant;
import org.springblade.auth.service.BladeClientDetailsServiceImpl;
import org.springblade.core.tenant.annotation.NonDS;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.Base64Util;
import org.springblade.core.tool.utils.StringUtil;
import org.springblade.core.tool.utils.WebUtil;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.oauth2.provider.ClientDetails;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * 优诺单点登录
 *
 */
@NonDS
@ApiSort(1)
@RestController
//@AllArgsConstructor
@Api(value = "优诺授权认证", tags = "授权接口")
@Slf4j
@RequestMapping("token/uino")
public class UinoTokenEndPoint {
	private static final Map<String, Object> userMap = new HashMap<>();
	@Resource
	private BladeClientDetailsServiceImpl bladeClientDetailsService;

	@Value("${datalink.url:http://192.168.1.190:30080}")
	private String datalinkUrl;
	@Value("${twin.uino.domainId:1224141613300088}")
	private Long domainId;

	/**
	 * 认证授权
	 * @return
	 */
	@GetMapping("oauth/authorize")
	public void authorize(@RequestParam Map<String, String> parameters,
							HttpServletResponse response) throws IOException {
		for (Map.Entry<String, String> entry : parameters.entrySet()) {
			log.info("name: {} -- value: {}", entry.getKey(), entry.getValue());
		}
		String responseType = parameters.get("response_type");
		String state = parameters.get("state");
		String client_id = parameters.get("client_id");
		String targetUrl = parameters.get("targetUrl");
		String redirect_uri = parameters.get("redirect_uri");
		// 验证合法性
		if (!responseType.equals("code")){
			log.error("response_type not be code.");
			response.sendRedirect(datalinkUrl);
		}
		bladeClientDetailsService.setSelectClientDetailsSql(AuthConstant.DEFAULT_SELECT_STATEMENT);
		bladeClientDetailsService.setFindClientDetailsSql(AuthConstant.DEFAULT_FIND_STATEMENT);
		ClientDetails clientDetails = bladeClientDetailsService.loadClientByClientId(client_id);
		if (clientDetails == null){
			log.error("client_id not found.");
			response.sendRedirect(datalinkUrl);
		}
		String code = RandomStringUtils.randomAlphanumeric(6);
		log.info("code={}", code);
		// 获取用户信息
		String userTicket = WebUtil.getCookieVal("cookie_user_ticket");
		if (StringUtil.isBlank(userTicket)){
			log.error("cookie_user_ticket is null");
			response.sendRedirect(datalinkUrl);
		}
		SsoUserInfo ssoUserInfo = SsoUtil.getUserInfo(userTicket);
		if (null == ssoUserInfo){
			log.error("获取用户信息为空");
			response.sendRedirect(datalinkUrl);
		}
		userMap.put(code, ssoUserInfo.getUser());
		response.sendRedirect(redirect_uri + "?code=" + code + "&state=" + state); ;
	}

	/**
	 * 根据code获取token
	 * @param parameters
	 * @return
	 */
	@PostMapping("oauth/token")
	public String token(@RequestParam Map<String, String> parameters){
		// 提取参数
		String grant_type = parameters.get("grant_type");
		String code = parameters.get("code");
		String redirect_uri = parameters.get("redirect_uri");
		String authorization = WebUtil.getHeader("Authorization");
		// 判断授权类型
		if (!grant_type.equals("authorization_code")){
			log.warn("grant_type: "+grant_type+" is not authorization_code");
			return R.fail("grant_type: "+grant_type+" is not authorization_code").toString();
		}
		// 验证client_id,client_secret
		String decode = Base64Util.decode(authorization.substring(6));
		String[] client = decode.split(":");
		bladeClientDetailsService.setSelectClientDetailsSql(AuthConstant.DEFAULT_SELECT_STATEMENT);
		bladeClientDetailsService.setFindClientDetailsSql(AuthConstant.DEFAULT_FIND_STATEMENT);
		ClientDetails clientDetails = bladeClientDetailsService.loadClientByClientId(client[0]);
		if (!(clientDetails != null && clientDetails.getClientSecret().substring(6).equals(client[1]))){
			log.error("client_id and client_secret invalid.");
			return R.fail("client_id and client_secret invalid.").toString();
		}
		// 验证code
		SsoUser user = (SsoUser) userMap.remove(code);
		if (user == null){
			log.warn("code: "+code+" is invalid");
			return R.fail("code: "+code+" is invalid").toString();
		}
		// 生成token
		String token = RandomStringUtils.randomAlphanumeric(32);
		log.info("token: {}", token);
		userMap.put(token, user);
		Map<String, Object> map  = new HashMap<>();
		map.put("access_token", token);
		map.put("token_type", "bearer");
		map.put("expires_in", 43200);
		map.put("scope", "all");
		return JSON.toJSONString(map);
	}

	/**
	 * 根据token获取用户信息
	 * @return
	 */
	@GetMapping("oauth/getUserInfo")
	public String getUserInfo(){
		// 提取token
		String token = WebUtil.getHeader("Authorization");
		SsoUser user = (SsoUser) userMap.remove(token);
		if (user == null){
			log.warn("token ["+token+"] is invalid");
			return R.fail("token is invalid").toString();
		}
		// 解析用户信息
		Map<String, Object> map = new HashMap<>();
		map.put("loginCode", user.getAccount());
		map.put("name", user.getName());
		map.put("domainId", domainId);
		return JSON.toJSONString(map);
	}

	@GetMapping("/store/domainId")
	public R storeDomainId(String subAppId){
		userMap.put("domainId", Long.valueOf(subAppId));
		return R.success("ok");
	}
}
